using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using UserMgr.Domain;
using UserMgr.Domain.Entities;
using UserMgr.Domain.ValueObjects;

namespace UserMgr.Infrastracture;

public class UserRepository:IUserRepository
{
    private readonly UserDbContext dbContext;
    private readonly IDistributedCache distributedCache;
    private readonly IMediator mediator;

    public UserRepository(UserDbContext dbContext, IDistributedCache distributedCache,IMediator mediator)
    {
        this.dbContext = dbContext;
        this.distributedCache = distributedCache;
        this.mediator = mediator;
    } 

    public async Task<User?> FindOneAsync(PhoneNumber phoneNumber)
    {
        return await dbContext.Users.SingleOrDefaultAsync(u=>u.PhoneNumber.Number==phoneNumber.Number&&u.PhoneNumber.RegionNumber==phoneNumber.RegionNumber);
    }

    public async Task<User?> FindOneAsync(Guid userId)
    {
        return await dbContext.Users.SingleOrDefaultAsync(u=>u.Id==userId);
    }

    public async Task<string?> FindPhoneNumberCodeAsync(PhoneNumber phoneNumber)
    {
        string fullNumber = phoneNumber.RegionNumber + phoneNumber.Number;
        string cacheKey = $"LoginByPhoneAndCode_Code_{fullNumber}";
        string? code = await distributedCache.GetStringAsync(cacheKey);
        distributedCache.RemoveAsync(cacheKey);
        return  code;
    }

    public async Task AddNewLoginHistoryAsync(PhoneNumber phoneNumber, string msg)
    {
        User? user = await FindOneAsync(phoneNumber);
        Guid? userId = null;
        if (user!=null)
        {
            userId = user.Id;
        }
        dbContext.UserLoginHistories.Add(new UserLoginHistory(userId,phoneNumber, msg));
    }

    public Task SavePhoneCodeAsync(PhoneNumber phoneNumber, string code)
    {
        string fullNumber = phoneNumber.RegionNumber + phoneNumber.Number;
        string cacheKey = $"LoginByPhoneAndCode_Code_{fullNumber}";
        return distributedCache.SetStringAsync(
            cacheKey,
            code,
            new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
        });
    }

    public Task<string?> RetrievePhoneCodeAsync(PhoneNumber phoneNumber)
    {
        throw new NotImplementedException();
    }

    public Task PublishEventAsync(UserAccessResultEvent @event)
    {
        return mediator.Publish(@event);
    }
}